package com.qianbao.qianbaobusiness.ui.webview;

import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;

import com.androidbase.okhttp.RequestMethod;
import com.androidbase.oklog.OkLogInterceptor;
import com.androidbase.utils.AndroidUtils;
import com.androidbase.utils.DeviceUuid;
import com.baseandroid.config.Api;
import com.baseandroid.config.Global;
import com.baseandroid.utils.EncryptUtil;
import com.facebook.stetho.okhttp3.StethoInterceptor;
import com.franmontiel.persistentcookiejar.ClearableCookieJar;
import com.franmontiel.persistentcookiejar.PersistentCookieJar;
import com.franmontiel.persistentcookiejar.cache.SetCookieCache;
import com.franmontiel.persistentcookiejar.persistence.SharedPrefsCookiePersistor;
import com.qianbao.qianbaobusiness.BuildConfig;
import com.qianbaocard.coresdk.SignUtil;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.Call;
import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.logging.HttpLoggingInterceptor;

public class SimpleOkhttpUtils {

    static class SingletonHolder {
        static SimpleOkhttpUtils INSTANCE = new SimpleOkhttpUtils();
    }

    public static SimpleOkhttpUtils getInstance() {
        return SingletonHolder.INSTANCE;
    }

    private OkHttpClient mHttpClient = null;
    private Handler mDelivery;

    public void init(Context context) {
        int cacheSize = 10 * 1024 * 1024; // 10 MiB
        Cache cache = new Cache(new File(AndroidUtils.getContext()
                .getCacheDir(), "okhttp3"), cacheSize);

        String userAgent = Build.MODEL + ";" + Build.VERSION.SDK_INT + ";" + BuildConfig.APPLICATION_ID + ";" + BuildConfig.VERSION_CODE + ";" + BuildConfig.VERSION_NAME;
        UserAgentInterceptor userAgentInterceptor = new UserAgentInterceptor(userAgent);

        ClearableCookieJar sCookieJar = new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(AndroidUtils
                .getContext()));

        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.cache(cache)
                .cookieJar(sCookieJar)
                .addNetworkInterceptor(userAgentInterceptor)
                .addInterceptor(headerInterceptor);

        if (BuildConfig.DEBUG) {
            HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
            loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            builder.addInterceptor(loggingInterceptor);
            builder.addNetworkInterceptor(new StethoInterceptor());
        }

        OkLogInterceptor okLogInterceptor = new OkLogInterceptor();
        builder.addInterceptor(okLogInterceptor);

        builder.connectTimeout(30, TimeUnit.SECONDS)
                .readTimeout(30, TimeUnit.SECONDS)
                .writeTimeout(30, TimeUnit.SECONDS);

        mHttpClient = builder.build();

        mDelivery = new Handler(Looper.getMainLooper());
    }

    public static class UserAgentInterceptor implements Interceptor {
        private static final String USER_AGENT_HEADER_NAME = "User-Agent";
        private final String userAgentHeaderValue;

        public UserAgentInterceptor(String userAgentHeaderValue) {
            this.userAgentHeaderValue = userAgentHeaderValue;
        }

        @Override
        public Response intercept(Chain chain) throws IOException {
            final Request originalRequest = chain.request();
            final Request requestWithUserAgent = originalRequest.newBuilder()
                    .removeHeader(USER_AGENT_HEADER_NAME)
                    .addHeader(USER_AGENT_HEADER_NAME, userAgentHeaderValue)
                    .build();
            return chain.proceed(requestWithUserAgent);
        }
    }

    public static Interceptor headerInterceptor = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request originalRequest = chain.request();

            Request.Builder newRequestBuilder = originalRequest.newBuilder();
            newRequestBuilder.addHeader("Accept-Resthub-Spec", "application/vnd.resthub.v2+json");
            newRequestBuilder.addHeader("Uni-Source", "qbsh_mer/Android (OS/" + Build.VERSION.SDK_INT + "APP/" + BuildConfig.VERSION_NAME + ")");

            String access_token = "";
            if (Global.getUserTokenInfo().getAc_token() != null) {
                access_token = Global.getUserTokenInfo().getAc_token();
            }

            HttpUrl.Builder builderUrl = originalRequest.url()
                    .newBuilder()
                    .addQueryParameter("_ac_token", access_token)
                    .addQueryParameter("_platform", "app")
                    .addQueryParameter("_os", "android")
                    .addQueryParameter("_sysVersion", "" + Build.VERSION.SDK_INT)
                    .addQueryParameter("_appVersion", "" + BuildConfig.VERSION_NAME)
                    .addQueryParameter("_model", "" + "" + Build.MODEL)
                    .addQueryParameter("_caller", "qbsh_mer")
                    .addQueryParameter("_cUDID", DeviceUuid.getDeviceId(Global.getContext()))
                    .addQueryParameter("_appChannel", "")
                    .addQueryParameter("_openUDID", DeviceUuid.getDeviceId(Global.getContext()));
            if (Api.isDevelop) {
                builderUrl.addQueryParameter("&__intern__show-error-mesg", "1");
            }

            String requestUrl = builderUrl.build().toString();
            StringBuilder queryString = new StringBuilder(requestUrl.substring(requestUrl.indexOf("?") + 1));

            StringBuilder postString = new StringBuilder();
            if (RequestMethod.supportBody(originalRequest.method())) {
                if (originalRequest.body() instanceof SimpleProgressRequestBody) {
                    FormBody.Builder formbuilder = new FormBody.Builder();
                    SimpleProgressRequestBody progressRequestBody = (SimpleProgressRequestBody) originalRequest
                            .body();
                    FormBody formBody = (FormBody) progressRequestBody.getDelegate();
                    for (int i = 0; i < formBody.size(); i++) {
                        postString.append(postString.length() > 0 ? "&" : "")
                                .append(formBody.encodedName(i))
                                .append("=")
                                .append(formBody.encodedValue(i) == null ? "" : formBody.encodedValue(i));
                    }
                }
            }

            String signvalue = SignUtil.generateSign(Global.getContext(), RequestMethod.supportBody(originalRequest
                    .method()) ? "POST" : "GET", queryString.append("&")
                    .toString(), postString.toString());
            builderUrl.addQueryParameter("_sign", signvalue);

            Request newRequest = newRequestBuilder.url(builderUrl.build()).build();

            Response response = chain.proceed(newRequestBuilder.build());
            String responseEncrypt = TextUtils.isEmpty(response.header("Content-Encrypt")) ? response
                    .header("Content_Encrypt") : response.header("Content-Encrypt");// Content-Encrypt="AES/QBSH"
            if (!TextUtils.isEmpty(responseEncrypt) && "AES/QBSH".equals(responseEncrypt)) {
                MediaType mediaType = response.body().contentType();
                try {
                    String responseContent = response.body().string();
                    responseContent = EncryptUtil.decryptBase64(responseContent);
                    return response.newBuilder()
                            .body(ResponseBody.create(mediaType, responseContent))
                            .build();
                } catch (Exception e) {
                    return response.newBuilder()
                            .body(ResponseBody.create(mediaType, ""))
                            .build();
                }
            }
            return response;
        }
    };

    public OkHttpClient getHttpClient() {
        return mHttpClient;
    }

    public static SimpleOkHttpRequest head(final String url) {
        return new SimpleOkHttpRequest(RequestMethod.HEAD, url);
    }

    public static SimpleOkHttpRequest get(final String url) {
        return new SimpleOkHttpRequest(RequestMethod.GET, url);
    }

    public static SimpleOkHttpRequest delete(final String url) {
        return new SimpleOkHttpRequest(RequestMethod.DELETE, url);
    }

    public static SimpleOkHttpRequest post(final String url) {
        return new SimpleOkHttpRequest(RequestMethod.POST, url);
    }

    public static SimpleOkHttpRequest put(final String url) {
        return new SimpleOkHttpRequest(RequestMethod.PUT, url);
    }

    public Handler getDelivery() {
        return mDelivery;
    }

    public void cancelTag(Object tag) {
        for (Call call : mHttpClient.dispatcher().queuedCalls()) {
            if (tag.equals(call.request().tag())) {
                call.cancel();
            }
        }

        for (Call call : mHttpClient.dispatcher().runningCalls()) {
            if (tag.equals(call.request().tag())) {
                call.cancel();
            }
        }
    }

}
